/**
 * @file step_motor.h
 * @author Neozng's little fan
 * @brief 步进电机控制头文件
 * @version 0.1
 * @date 2023-12-15
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef STEP_MOTOR_H
#define STEP_MOTOR_H

#include "main.h"
#include "tim.h"
#include "bsp_pwm.h"
#include "bsp_gpio.h"
#include <stdint-gcc.h>
#include "trapezoid.h"

#define STEP_MOTOR_CNT 7 //六个自由度，多设一个吧

/*
先考虑一下有哪些需要封装的变量
首先步进电机的使能和方向控制引脚需要传进去
然后还有信号引脚，这个对应的是pwm的输出通道和对应的定时器

然后就是步进电机的工作模式：
控制速度和控制角度
速度是通过改pwm频率或者电平翻转频率实现的
角度是通过脉冲计数实现的
然后二者都需要知道pwm的频率设置，还有细分角度才能计算，所以初始化的时候这些参数也是必要的（用于后续计算）

控制角度可能要单独写一个函数
传给pwm回调函数调用
所以步进电机的封装也包含了对pwm实例的操作

速度控制也需要单独封装一个函数

这样看的话
步进电机需要封装的变量有：
控制器引脚
pwm通道
pwm实例（回调函数）
初始角度和初始速度
然后再向下写
*/

//计算速度和角度后的返回值
typedef struct
{
    float pulse_count;
    int32_t pulse_ccr;
    
}SAreturn;

typedef struct
{
    //一些初始设置

    float angle;
    float speed;

    float Init_perangle; //初始设置的(步距角/细分数)
    float Init_frequency;//pwm的输出频率(时钟频率/预分频)
    PWM_Init_Config_s pwm_init_config;
    //步进电机的使能和方向引脚，主要用到的是 *GPIOx & GPIO_Pin 

    GPIO_Init_Config_s ENA;
    GPIO_Init_Config_s DIR;

    // 使用的定时器类型及通道

    TIM_HandleTypeDef *htim;
    uint32_t Channel;

    uint16_t mode; //模式选择，1是只有速度控制，一直转；2是速度和角度的设置(后续考虑加入不同算法的模式)
    int32_t count; //计数标志，初始配零就好

    SAreturn sareturn;  //储存返回值

    Trapecal_param trape_param;   //模式三才会用到的梯形加减速计算中的配置函数
    Trapecal_medium trape_medium;  //梯形加减速计算中的中间计算值

    float abs_pulsecount;  //电机一共记过的脉冲数，正转则加，反转则减
    float abs_angle;       //电机相较于初始位置移动的绝对角度  
    float set_angle;

    uint8_t dir_flag;

} Step_Init_Config_s;

typedef struct
{
    //一些初始设置

    float angle;
    float speed;

    float Init_perangle; //初始设置的(步距角/细分数)，注意除的是细分数不是pluse/rev！！！
    float Init_frequency;//pwm的输出频率，就是预分频后的频率即可。因为ccr是可以后期设置的。cubemx里的pulse似乎设置的就是初始的ccr.然后设置一个pulse_ccr,这个是要在中断里使ccr自增的值，最后脉冲的频率就是这里算出的频率再除以pulse_ccr

    //步进电机的使能和方向引脚，主要用到的是 *GPIOx & GPIO_Pin 

    GPIO_Init_Config_s ENA;
    GPIO_Init_Config_s DIR;
    PWMInstance *pwm_instance;

    // 使用的定时器类型及通道

    TIM_HandleTypeDef *htim;
    uint32_t Channel;

    uint16_t mode; //模式选择，1是只有速度控制，一直转；2是速度和角度的设置(后续考虑加入不同算法的模式)
    int32_t count;

    SAreturn sareturn;  //储存返回值

    Trapecal_param trape_param;   //模式三才会用到的梯形加减速计算中的配置函数
    Trapecal_medium trape_medium;  //梯形加减速计算中的中间计算值

    float abs_pulsecount;
    float abs_angle;
    float set_angle;

    uint8_t dir_flag;

} StepInstance;

StepInstance *StepInit(Step_Init_Config_s *Step_Init_Config);
void Set_abs_SA(StepInstance *Step_Motor,float set_angle,float speed);
//void Rotate_abs_SA(StepInstance *Step_Motor);
void Rotate_Relative_SA(StepInstance *Step_Motor);
//void StepMotor_Set_absSA(StepInstance *Step_Motor,float angle,float speed);
void OC_Callback_SA_in(StepInstance *Step_Motor);
void OC_Callback_S_in(StepInstance *Step_Motor);
void OC_Callback_S();
void OC_Callback_SA();
//void StepMotor_Stop(StepInstance *Step_Motor);
//void StepMotor_Start(StepInstance *Step_Motor);
void OC_Callback_Trape_in(StepInstance *Step_Motor);
void OC_Callback_Trape();
void StepMotor_TrapeSet(StepInstance *Step_Motor,float angle,float constSpeed,float accelSpeed,float decelSpeed);
void StepMotor_TrapeSetStep(StepInstance *Step_Motor, uint32_t total_step);
void Set_SA(StepInstance *Step_Motor,float speed,uint16_t mode);
#endif // SERVO_MOTOR_H